package com.stegniy.queue;

import java.util.NoSuchElementException;

public class LinkedQueue<E> implements Queue<E> {

    private class Node<E> {
        public E data;
        public Node next;

        public Node(E data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    private Node<E> head = null;
    private Node<E> tail = null;

    public boolean isEmpty() {
        return head == null;
    }

    public int size() {
        int count = 0;
        for (Node node = head; node != null; node = node.next) {
            count++;
        }
        return count;
    }

    /*Inserts the specified element into this queue if it is possible to do
      so immediately without violating capacity restrictions*/
    public boolean offer (E e) {
        Node newNode = new Node(e, null);
        if (isEmpty()) {
            head = newNode;
        } else {
            tail.next = newNode;
        }
        tail = newNode;
        return true;
    }

    /*Retrieves, but does not remove, the head of this queue*/
    public E element() {
        if (head == null) {
            throw new NoSuchElementException("the queue is empty");
        } else {
            return head.data;
        }
    }

    /*Retrieves, but does not remove, the head of this queue,
      or returns null if this queue is empty*/
    public E peek() {
        if (head == null) {
            return null;
        } else {
            return head.data;
        }
    }

    /*Retrieves and removes the head of this queue,
      or returns null if this queue is empty*/
    public E poll() {
        if (head == null) {
            return null;
        }
        E item = head.data;
        if (tail == head) {
            tail = null;
        }
        head = head.next;
        return item;
    }

    /*Retrieves and removes the head of this queue*/
    public E remove() {
        if (head == null) {
            throw new NoSuchElementException("the queue is empty");
        }
        E item = head.data;
        if (tail == head) {
            tail = null;
        }
        head = head.next;
        return item;
    }
}